package com.zzx.resource.security;


import com.zzx.resource.exception.CustomAccessDeniedHandler;
import com.zzx.resource.exception.GlobalOauth2ExceptionTranslator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.web.AuthenticationEntryPoint;

/**
 * ResourceServerConfig 资源服务配置
 **/
@EnableResourceServer
// 在方法采用注解 更细粒度的授权 @PreAuthorize("hasAuthority('xxx')") 拥有xxx权限才能访问对应接口
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    @Autowired
    ResourceServerProperties resourceServerProperties;
    @Autowired
    TokenStore tokenStore;
    @Bean
    public AuthIgnoreConfig authIgnoreConfig() {
        return new AuthIgnoreConfig();
    }

    /**
     * 配置对资源授权
     */
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .exceptionHandling()
//                .and()
//                .authorizeRequests()
//                .antMatchers("/**").permitAll()
//                .anyRequest().authenticated()
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)// 以下为全局配置所需保护的资源路径及需要的权限 这里放行所有
                // 可以通过注解在Controller细粒度的控制
                // hasRole() 判断角色 hasAuthority() 判断权限

                .and().csrf().disable();

        // 配置不登录可以访问 - 放行路径配置
        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http
                .authorizeRequests();
        authIgnoreConfig().getUrls().forEach(url -> registry.antMatchers(url).permitAll());
        registry.anyRequest().authenticated();
    }

    /*@Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        RemoteTokenServices services = new RemoteTokenServices();
        // 资源服务器从远程check_token时 只保存了部分信息，自定义获取
        DefaultAccessTokenConverter converter = new DefaultAccessTokenConverter();
        converter.setUserTokenConverter(new MyUserAuthenticationConverter());
        services.setAccessTokenConverter(converter);
        // 远程认证的基本信息
        services.setClientId(resourceServerProperties.getClientId());
        services.setCheckTokenEndpointUrl(resourceServerProperties.getTokenInfoUri());
        services.setClientSecret(resourceServerProperties.getClientSecret());
        // 自定义异常转换
        AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint();
        ((OAuth2AuthenticationEntryPoint) authenticationEntryPoint).setExceptionTranslator(new GlobalOauth2ExceptionTranslator());
        resources
                .tokenServices(services)
                .accessDeniedHandler(new CustomAccessDeniedHandler())
                .authenticationEntryPoint(authenticationEntryPoint);
    }*/
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        // 自定义异常转换
        AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint();
        ((OAuth2AuthenticationEntryPoint) authenticationEntryPoint).setExceptionTranslator(new GlobalOauth2ExceptionTranslator());
        resources
                .tokenStore(tokenStore)
                .accessDeniedHandler(new CustomAccessDeniedHandler())
                .authenticationEntryPoint(authenticationEntryPoint);
    }
}


